/*    
 * Copyright � 2007 Telenor R&I, iLabs. All Rights Reserved.
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2.1 of the License, or (at your option) any later version.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this library; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
 *
 * Please contact iLabs Telenor R&I, software@ilabs.mobi, Snar�yveien 30, 1331 
 * Fornebu, Norway or visit <a href="http://www.iLabs.no">www.iLabs.no</a> for
 * additional information.
 */

package mobi.ilabs.authentication;

import java.util.HashMap;
import java.util.Map;


import mobi.ilabs.EILog;

import org.apache.commons.logging.Log;


/**
 * Simple authentication framework for the object storage.
 *
 */
public final  class Authenticator {

    /**
     * Hidden constructor for utility class.
     */

    private Authenticator() {
    }


    /**
     * Log instance used by this class.
     */
    private static final Log LOG = EILog.getLog(Authenticator.class);


    /**
     * Map storing the secrets used by test users.
     * Should never, ever, be used in a production setting.
     * XXX these usernames and passwords should be stored in a
     *     property file, and that property file should never be
     *     present in production facilities.
     */
    private static  Map <String, String> testUserSecrets = null;

    public static synchronized  Map <String, String> getTestUserSecrets() {
        if (testUserSecrets == null) {
            testUserSecrets = new HashMap <String, String> ();
            testUserSecrets.put("anonymous", "sludder");
            testUserSecrets.put("TestUser",  "Sludder");
        }
        return testUserSecrets;
    }

    /**
     * An authenticator that will grant access for
     * anonymous users.
     */
    private static final RawAuthenticator
    ANONYMOUS_AUTHENTICATOR_FOR_TEST_ONLY =
        new RawAuthenticator() {


        public AuthenticationResult rawAuthenticate(
                final String user,
                final String credential) {
            AuthenticationResult result;
            final String secret = getTestUserSecrets().get(user);
            if ((secret != null) && secret.contains(credential)) {
                // sloppy
                result = AuthenticationResult.AUTHENTICATED;
            } else {
                result = AuthenticationResult.REJECTED;
            }
            LOG.debug("Authenticating user "
                    + user
                    + " cred = "    + secret +
                      ", result = " + result);
            return result;
        }
    };

    /**
     * Allow nobody.
     */
    private static final RawAuthenticator DISMISSIVE_AUTHENTICATOR =
        new RawAuthenticator() {

        public AuthenticationResult rawAuthenticate(
                final String user,
                final String credential) {
            return AuthenticationResult.REJECTED;
        }
    };

    /**
     * Allow only those with proper Google credentials.
     */
    private static final RawAuthenticator GOOGLE_AUTHENTICATOR =
        // new AuthenticatorForXMPP(Config.getGoogleXmppServerHostname());
        new GoogleAccountAuthenticator();  // See if this does any good

    /**
     * Allow only those with proper Horus credentials.
     */
    private static final RawAuthenticator HORUS_AUTHENTICATOR =
        new AuthenticatorForXMPP("horus.nta.no");

    /**
     * Authenticate a user given an userId and a secret.
     * @param userId
     * @param secret
     * @return -1 => failed, +1 => authenticated , 0 => unknown
     */
    public static int authenticate(
            final String userId,
            final String secret) {
        LOG.debug("Trying to authenticate user = '" + userId + "' pw = '"
                + secret + "'");
        if (userId == null) {
            return -1;
        } else {
            return CachedAuthenticator.getInstance().authenticate(userId,
                    secret);
        }
    }

    /**
     * If flag is set, then allow anonymous test users.
     */
    private static boolean anonymousTestUsersIsEnabled = false;


    /**
     * Enable anonymous test users.  This should -never- -ever-
     * be done in a production environment!
     *
     */
    public static void enableAnonymousTestUsers() {
        anonymousTestUsersIsEnabled = true;
    }

    /**
     * Find the authenticator that should be used to authenticate this user.
     *
     * @param userid  String with an user identifier.
     *                Get the proper authenticator to use for this user.
     * @return The authenticator appropriate for the userid given as parameter.
     */
    public  static  RawAuthenticator getAuthenticator(final String userid) {
        assert (userid != null);
        if (userid.endsWith("@gmail.com")) {
            return GOOGLE_AUTHENTICATOR;
        }
        if (userid.endsWith("@horus.nta.no")) {
            return HORUS_AUTHENTICATOR;
        }
        if (anonymousTestUsersIsEnabled) {
            return ANONYMOUS_AUTHENTICATOR_FOR_TEST_ONLY;
        } else {
            return DISMISSIVE_AUTHENTICATOR;
        }
    }

}
